<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- <iframe style="width: 1200px;height: 800px;" frameborder="0" scrolling="no" src="//vote.weibo.com/widget?vid=136117345&isTitle=1&isBorder=1&pad=15&titleSize=m&skin=1"></iframe>

    <iframe src="http://localhost:5173/" frameborder="0" style="width: 1200px;height: 800px;"></iframe>
    <iframe src="http://localhost:8080/" frameborder="0" style="width: 1200px;height: 800px;"></iframe> -->
  </body>
  <!-- <script>
    // 定义一个存放数据的数组
    var callbacks = [];
    // 定义当前nextTick运行状态防止重复推送
    var pending = false;

    // 通过Promise触发当前函数放到微任务中进行调用

    function flushCallbacks() {
      pending = false;
      // 重新复制一份当前的数组 slice重新在内存中开辟一块空间来存储这个数组
      // 对于示例来说也可以不重新存储,这是在vue2中作者写的。可能是为了防止原数组改动会造成什么影响
      var copies = callbacks.slice(0);
      // 清空之前的数组 因为已经复制一份了
      callbacks.length = 0;
      for (let i = 0; i < copies.length; i++) {
        copies[i]();
      }
    }

    // 接收一个参数
    function nextTick(cb) {
      callbacks.push(() => {
        cb();
      });
      // 判断当前的方法是否在执行中
      if (!pending) {
        pending = true;
        Promise.resolve().then(flushCallbacks);
      }
    }

    function testNextTick() {
      nextTick(() => {
        console.log("1");
      });
      console.log("2");
    }
    testNextTick()
    // 执行结果先打印2 在打印1
  </script> -->
  <script>
    const callbacks = [];
    let pending = false;
    function flushCallbacks() {
      // 重置标记，允许下一个 nextTick 调用
      pending = false; /*执行所有cb回调函数*/
      for (let i = 0; i < callbacks.length; i++) {
        callbacks[i]();
      } // 清空回调数组，为下一次调用做准备
      callbacks.length = 0;
    }

    function nextTick(cb) {
      let _resolve;
      callbacks.push(() => {
        if (cb) {
          cb();
        } else if (_resolve) {
          _resolve();
        }
      });
      if (!pending) {
        pending = true;
        Promise.resolve().then(flushCallbacks);
      }
      console.log("1", 1);
      if (!cb) {
        return new Promise((resolve, reject) => {
          _resolve = resolve;
        });
      }
    }
    let message = "初始消息";

    let a = 1;
    async function testNextTick() {
      // await nextTick(); // nextTick 返回 Promise
      await nextTick();
      a++;
      console.log("测试开始：", message, a); // 输出1: 初始消息
    }
    testNextTick();
    // nextTick(() => {
    //   message = "更新后的消息";
    //   console.log("更新后的消息", message); // 输出1: 初始消息
    // });
    //异步的执行方式
    // Web api是异步操作(fetch 请求、promise、计时器)及其回调等待完成的地方
    // Call stack是调用堆栈是一个LIFO(后进先出)结构
    // task queue （任务队列 宏任务）是一个FIFO(先进先出)结构
    // job queue （作业队列 微任务）是一个FIFO(先入先出)结构
    // 现在是有趣的部分：作业队列(微任务)优先级高于任务队列(宏任务)。 事件循环从作业队列中取出promise回调并将其放入调用堆栈中。 然后，调用堆栈执行promise回调：
    // 最后，事件循环将计时器回调从任务队列中出队到调用堆栈中。 然后，调用堆栈执行计时器回调：
  </script>
  <style>
    .a {
      color: rgba(0, 17, 255, 0.418);
    }
  </style>
</html>
